Skip to content

Emit type-matched na sentinels on bare-na reassignment#55

Merged
luisleo526 merged 1 commit into
mainfrom
fix/na-reassignment-retype
Jul 11, 2026
Merged

Emit type-matched na sentinels on bare-na reassignment#55
luisleo526 merged 1 commit into
mainfrom
fix/na-reassignment-retype

Conversation

@luisleo526

Copy link
Copy Markdown
Contributor

What

x := na lowered as x = na<double>(); regardless of LHS type. NaN assigned into int/int64/bool storage is UB — ARM64 FCVTZS(NaN)=0 silently destroys the na sentinel (is_na false forever), while x86-64's CVTTSD2SI(NaN) coincidentally equals INT64_MIN (the sentinel), masking the bug there. Exemplar: a daily session-open timer (int64, := na each new day) never re-armed on ARM64, permanently disabling an open-suppression gate → phantom session-open entries.

Fix: the ctor-initializer path already re-typed bare na; the two := lowering sites and the function-var-init block now do too, via a resolver that returns the declared scalar type (int / int64_t with epoch promotion / bool / string; None leaves double, collections, UDTs, drawing types untouched), gated on the RHS being exactly a bare na.

Gates (author + independent fresh-context R7, both green)

  • 5 verbatim RED tests fail pre-fix; 7/7 post-fix. Full pytest 1480 passed / 1 skipped; corpus compile sweep 254.
  • Whole-corpus differential transpile: 0/254-265 outputs changed (byte-identical) — provably neutral where the shape is absent.
  • Exemplar converges to an exact 95 = 95 trade-for-trade TV match (was 105 vs 95, moderate → excellent); the load-bearing int-na-reset sentinels (KI-34 orb-avwap 291/291; turtle 623) are byte-identical.
  • Private validation full sweep (412): exactly 1 UP / 0 DOWN, error inventory stable — the 43 strategies carrying the latent shape all held tier.

🤖 Generated with Claude Code

A Pine `x := na` reassignment lowered as `x = na<double>();` for every
LHS type. Assigning NaN into an int/int64/bool member is UB: on ARM64
FCVTZS(NaN) yields 0, silently destroying the na sentinel (is_na stays
false forever), while x86-64's CVTTSD2SI(NaN) coincidentally lands on
INT64_MIN — the sentinel value — masking the bug on that platform.
Exemplar: a daily session-open timer (int64, reset to na each new day)
never re-armed on ARM64, permanently disabling an open-suppression gate
and emitting phantom session-open entries.

The constructor-initializer path already re-typed bare na to the member
type; the two `:=` lowering sites and the function-var-init block did
not. A new resolver returns the declared scalar type (int / int64_t
with the epoch promotion / bool / string; None for double, collections,
UDTs, and drawing types, which keep their current lowering), gated on
the RHS being exactly a bare na.

Provably neutral where the shape is absent: transpiling the entire
corpus (254-265 sources) with and without the fix produces byte-
identical output. The exemplar converges to an exact trade-for-trade
TV match; the load-bearing int-na-reset sentinels are byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@luisleo526 luisleo526 merged commit c21281a into main Jul 11, 2026
9 checks passed
@luisleo526 luisleo526 deleted the fix/na-reassignment-retype branch July 11, 2026 01:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant